package cn.coufran.springboot.starter.auth.impl.token;

import java.util.Date;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 基于Map的Refresh Token本地存储
 * @author Coufran
 * @version 1.1.0
 * @since 1.1.0
 */
public class LocalMapRefreshTokenRepository implements RefreshTokenRepository {
    /** Map存储 */
    private volatile Map<String, Date> refreshTokens = new ConcurrentHashMap<>();
    /** 上次清理后的个数（用于清理过期Token） */
    private volatile int lastCleanSize = 0;

    /**
     * 保存Refresh Token（原子操作）
     * @param refreshToken refresh token
     * @param expireTime 过期时间
     */
    @Override
    public void save(String refreshToken, Date expireTime) {
        this.clean();
        refreshTokens.put(refreshToken, expireTime);
    }

    /**
     * 删除并返回是否存在Refresh Token（原子操作）
     * @param refreshToken refresh token
     * @return 存在返回true
     */
    @Override
    public boolean delete(String refreshToken) {
        Date expireTime = refreshTokens.remove(refreshToken);
        if (expireTime == null) {
            return false;
        }
        if (System.currentTimeMillis() > expireTime.getTime()) {
            return false;
        }
        return true;
    }

    /**
     * 清理Map存储
     */
    private void clean() {
        // 只有达到上次清理容量的二倍才清理
        if (refreshTokens.size() < lastCleanSize * 2 + 1) {
            return;
        }
        long now = System.currentTimeMillis();
        Set<String> refreshTokenKeySet = refreshTokens.keySet();
        for (String refreshToken : refreshTokenKeySet) {
            Date expireTime = refreshTokens.get(refreshToken);
            if (expireTime == null) {
                continue;
            }
            if (expireTime.getTime() < now) {
                refreshTokens.remove(refreshToken);
            }
        }
        lastCleanSize = this.refreshTokens.size();

    }
}
